//+--------------------------------------------------------------------------------
//| Copyright (c) 2012 - 2013 ### an.vuongngocduy
//| This file is a part of Compact Game Engine (CGE)
//+--------------------------------------------------------------------------------
#ifndef __CGE_RECT_H__
#define __CGE_RECT_H__

#include "cgeVector2.h"
#include "cgeDimension2.h"

namespace cge
{
	namespace std
	{
		//! Define an rectangle area at specified position by using 4 values : left, top, right, bottom
		template<class TVal>
		class Rect
		{
		public:
			//! Default constructor
			Rect()
				: Left(0), Top(0), Right(0), Bottom(0)
			{}


			//! Construct new rectangle from specified elements
			Rect(TVal l, TVal t, TVal r, TVal b)
				: Left(l), Top(t), Right(r), Bottom(b)
			{}


			//! Destructor
			~Rect() {}


			//! Get size of rectangle
			Dimension2<TVal> Dimension() const
			{
				return Dimension2<TVal>(Right - Left, Bottom - Top);
			}


			//! Set elements' values for rectangle
			void Set(TVal l, TVal t, TVal r, TVal b)
			{
				Left = l; Top = t; Right = r; Bottom = b;
			}


			//! Set elements' values for rectangle from position and size
			void Set(const Vector2<TVal>& topLeftPos, const Dimension2<TVal>& dimension)
			{
				Left = topLeftPos.X; Top = topLeftPos.Y; Right = Left + dimension.Width; Bottom = Top + dimension.Height;
			}


			//! Test whether 2 rectangles collided with each other
			template<class TArg>
			b8 IsCollided(const Rect<TArg>& rect) const
			{
				b8 isCollided = ( Right > rect.Left && Bottom > rect.Top )
							  ||( Left < rect.Right && Top < rect.Bottom )
							  ||( Left < rect.Right && Bottom > rect.Top )
							  ||( Right > rect.Left && Top < rect.Bottom );			
				return isCollided;
			}


			/*! Check and return intersection rect between 2 rectangle . 
			 * @return Intersection zone of 2 rects.
			 *		   If there are no intersection , the returned rect will have 0 area
			 */
			template<class TArg>
			Rect Intersect(const Rect<TArg>& rect) const
			{
				Rect res;

				if( Right > rect.Left && Bottom > rect.Top )
					res.Set(rect.Left, rect.Top, Right, Bottom);
				
				if( Left < rect.Right && Top < rect.Bottom )
					res.Set(Left, Top, rect.Right, rect.Bottom); 
				
				if( Left < rect.Right && Bottom > rect.Top )
					res.Set(Left, Rect.Top, rect.Right, Bottom);
				
				if( Right > rect.Left && Top < rect.Bottom )
					res.Set(rect.Left, Top, Right, rect.Bottom);

				return res;
			}


		public:
			union
			{
				struct {  TVal Left, Top, Right, Bottom; };
				TVal Elements[4];
			};
		};

		//! Unsigned integer rect
		typedef Rect<u32> Rectu;

		//! Signed integer rect
		typedef Rect<s32> Recti;

		//! Floating number rect
		typedef Rect<f32> Rectf;

		//! Double precision floating number rect
		typedef Rect<f64> Rectd;
	}
}

#endif//__CGE_RECT_H__